//данная программа генерирует файлы общих библиотек

#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <queue>

using namespace std;

#include "binfile.h"
#include "both.h"


struct NPLib {
  Int32 f;
  Int8 comp;
  bool mark;
};

vector<NPLib> npLib;
Int64 fCount, fHalfMask;
Int8 fLen, n;
queue<Int64> classQ;

BinFile writer, reader;

bool TestLPElem(Int64 &f) {
  size_t s = 0, e = npLib.size();
  while(s + 1 < e) {
    size_t m = s + (e - s)>>1;
    if (npLib[m].f <= f) s = m;
    else e = m;
  }
  if (s > e) return false;
  if (npLib[s].f != f) return false;
  if (!npLib[s].mark) {
    npLib[s].mark = true;
    return true;
  }
  return false;
}

inline void MarkClassBy(const Int64 f) {
  classQ.push(f);
  while(!classQ.empty()) {
    Int64 fTmp = classQ.front(); classQ.pop();
    for(Int8 i = 0; i < Shift.size(); i++) {
      if (i != 0) fTmp = swapvars(fTmp, Shift[i], n);
      Int64 fTmp2 = fTmp, fTmp21 = fTmp, fTmp22 = fTmp, fTmp23 = fTmp, fTmp24 = fTmp;
      for(Int8 j = 0; j < Gray.size(); j++) {
        if (j != 0) {
          fTmp2 = negbyvar(fTmp2, Gray[j], n);
          fTmp21 = d1byvar(fTmp21, Gray[j], n);
          fTmp22 = d2byvar(fTmp22, Gray[j], n);
          fTmp23 = d3byvar(fTmp23, Gray[j], n);
          fTmp24 = d4byvar(fTmp24, Gray[j], n);

          if (TestLPElem(fTmp21)) classQ.push(fTmp21);
          if (TestLPElem(fTmp22)) classQ.push(fTmp22);
          if (TestLPElem(fTmp23)) classQ.push(fTmp23);
          if (TestLPElem(fTmp24)) classQ.push(fTmp24);
        }
        if (TestLPElem(fTmp2)) classQ.push(fTmp2);
      }
    }
  }
}

inline void LoadInfo() {
  ostringstream oss;
  fLen = 1 << n;
  fCount = (Int64)1 << fLen;

  fHalfMask = ((Int64)1 << (fLen >> 1)) - 1;

  oss << "binfile" << (int)n << "v_np.mbf";
  reader.open(oss.str(), BIN_FILE_READ);
  
  while(!reader.isEnd()) {
    NPLib t;
    reader.read(t.f);
    reader.read(t.comp);
    t.mark = false;
    npLib.push_back(t);     
    //cout << t.f << endl;
  }

  oss.str("");
  oss << "binfile" << (int)n << "v_lp.mbf";
  writer.open(oss.str(), BIN_FILE_WRITE);
  MakeAddArrays(n);

  cout << "Writing!" << endl;
}

inline void SaveInfo(const Int64 f, const Int8 fComp) {
  writer.write((Int32)f);
  writer.write(fComp);
}

int main () {
  n = 5;
  LoadInfo();

  Int8 fComp;
  
  for(size_t i = 0; i < npLib.size(); i++)
   if (!npLib[i].mark) {
      fComp = npLib[i].comp;
      MarkClassBy(npLib[i].f);
      cout << npLib[i].f << endl;
      SaveInfo(npLib[i].f,fComp);
    }
  
  return 0;
}
